﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DevExpress.XtraBars;
using DevExpress.XtraEditors;
using ProgramMain.Framework;
using ProgramMain.Google;
using ProgramMain.Layers;
using ProgramMain.Database;
using ProgramMain.Database.SimpleOpticNetDBTableAdapters;

using HashItem = System.Collections.Generic.KeyValuePair<double, int>;
using TMouseActionMode = ProgramMain.OpticNet.OpticNetDesignPanel.TMouseActionMode;

namespace ProgramMain.OpticNet
{
    public partial class OpticNetCtl : ProgramMain.Framework.BaseDetailCtl
    {
        private MapLayer MapLayer;
        private NetLayer NetLayer;
        private MeasurementLayer MeasurementLayer;
        private bool _shiftKey { get; set; }
     
        private bool _isDragAndDropMeause { get; set; }

        private bool _dragAndDropVertex = false;
        private bool IsDragAndDropVertex
        {
            get { return _dragAndDropVertex; }
            set
            {
                _dragAndDropVertex = value;
                if (NetLayer != null) NetLayer.IsDragDropVertex = value;
            }
        }

        public void ShowTranzitVertex(bool showTranzit)
        {
            if (NetLayer != null)
            {
                NetLayer.ShowTranzitVertex = showTranzit;
                this.NetLayer.Update();
                this.Invalidate();
            }
        }

        public int Level
        {
            get
            {
                return MapLayer.Level;
            }
            set
            {
                if (value != MapLayer.Level)
                {
                    MapLayer.Level = value;
                    NetLayer.Level = value;
                    MeasurementLayer.Level = value;
                    if (LevelValueChanged != null)
                        LevelValueChanged(this, new OpticNetDesignPanel.LevelValueArgs(value));
                }
            }
        }
        public event EventHandler<OpticNetDesignPanel.LevelValueArgs> LevelValueChanged;

        public Coordinate CenterCoordinate
        {
            get
            {
                return MapLayer.CenterCoordinate;
            }
            set
            {
                MapLayer.CenterCoordinate = value;
                NetLayer.CenterCoordinate = value;
                MeasurementLayer.CenterCoordinate = value;
            }
        }

        private bool CaptureMoveMap = false;
        private bool moveVertexCheck = false;
        private bool cableTunnelCheck = false;
        private bool rulerCheck = false;
        public FrmHotCableTunnels hotCableTunnels { get; private set; }
        public event EventHandler OnTurnOffEditMode;

        private Point MousePreviousLocation;
        private Coordinate CoordinatePreviosLocation;
        private int PreviousObjectID;

        public OpticNetCtl()
        {
            InitializeComponent();

            Graphics GDIcontext = this.CreateGraphics();
            Bitmap GDIbmp = new Bitmap(1, 1, GDIcontext);
            PixelFormat PIFormat = GDIbmp.PixelFormat;

            Coordinate coordinate = new Coordinate(
                Properties.Settings.Default.StartLongitude,
                Properties.Settings.Default.StartLatitude);

            GoogleSearch.GoogleSearch search = new GoogleSearch.GoogleSearch(coordinate);
            List<GoogleSearch.SearchResult> results = search.Search();
            if (results.Count > 0)
            {
                string[] addressComponents = (from q in results[0].AddressComponents where q.Types.First() == "locality" select q.LongName).ToArray();
                if (addressComponents.Length > 0)
                    GoogleSearch.GoogleSearch.Locality = addressComponents[0];
            }

            MapLayer = new MapLayer(this.Width, this.Height, coordinate, Properties.Settings.Default.StartZoomLevel, this, PIFormat);
            NetLayer = new NetLayer(this.Width, this.Height, coordinate, Properties.Settings.Default.StartZoomLevel, this, PIFormat);
            MeasurementLayer = new MeasurementLayer(this.Width, this.Height, coordinate,
                                                    Properties.Settings.Default.StartZoomLevel, this, PIFormat) { RulerType = 1 };
            MapLayer.DrawLayerBuffer += Layer_DrawBufferChanged;
            NetLayer.DrawLayerBuffer += Layer_DrawBufferChanged;
            MeasurementLayer.DrawLayerBuffer += Layer_DrawBufferChanged;

            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.Opaque, true);
            SetStyle(ControlStyles.SupportsTransparentBackColor, false);

            this.MouseWheel += new MouseEventHandler(OpticNetCtl_MouseWheel);


        }

        private void OpticNetCtl_Resize(object sender, EventArgs e)
        {
            if (MapLayer.Terminating) return;

            MapLayer.Resize(this.Width, this.Height);
            NetLayer.Resize(this.Width, this.Height);
            MeasurementLayer.Resize(this.Width, this.Height);
        }

        private void DrawOpticNet(Graphics clientDC, Rectangle ClipRectangle)
        {
            if (MapLayer.Terminating) return;

            //clientDC.Clear(Color.White);
            MapLayer.DrawBuffer(clientDC, ClipRectangle);
            NetLayer.DrawBuffer(clientDC, ClipRectangle);
            MeasurementLayer.DrawBuffer(clientDC, ClipRectangle);
        }

        public void RefreshControl()
        {
            MapLayer.Update(new Rectangle(0, 0, Width, Height));
            NetLayer.ReloadData();
        }

        private void OpticNetCtl_Paint(object sender, PaintEventArgs e)
        {
            if (MapLayer.Terminating) return;

            Graphics g = e.Graphics;
            if (g != null)
            {
                g.InterpolationMode = InterpolationMode.Low;
                g.CompositingQuality = CompositingQuality.HighSpeed;
                g.SmoothingMode = SmoothingMode.HighSpeed;

                DrawOpticNet(g, e.ClipRectangle);
            }
        }

        private void Layer_DrawBufferChanged(object sender, GraphicLayer.InvalidateLayerEventArgs e)
        {
            if (MapLayer.Terminating) return;
            if (e == GraphicLayer.InvalidateLayerEventArgs.Empty)
                this.Invalidate();

            else
                this.Invalidate(e.ClipRectangle);
        }

        public void ControlClosing()
        {
            MapLayer.Terminating = true;
            NetLayer.Terminating = true;
            MeasurementLayer.Terminating = true;

            CaptureMoveMap = false;
        }

        public void SetCenterMap()
        {
            if (MapLayer.Terminating) return;

            CenterCoordinate = new Coordinate(
                    Properties.Settings.Default.StartLongitude,
                    Properties.Settings.Default.StartLatitude);
        }

        public void MoveCenterMapObject(decimal longitude, decimal latitude)
        {
            if (MapLayer.Terminating) return;

            CenterCoordinate = new Coordinate(longitude, latitude);
        }
        public void SetRulerType(int rulerType)
        {
            MeasurementLayer.RulerType = rulerType;
            MeasurementLayer.Update();
        }
        public void SetMoveEditMode(TMouseActionMode bMouseActionMode, OpticNetDesignPanel.TMousePopUpMode mousePopUpMode)
        {
            switch (bMouseActionMode)
            {
                case TMouseActionMode.CableTunnelMode:
                    if (mousePopUpMode == OpticNetDesignPanel.TMousePopUpMode.None)
                    {
                        cableTunnelCheck = !cableTunnelCheck;
                      //  moveVertexCheck = cableTunnelCheck;
                    }
                    if (!CheckSecurityEditAction()) return;
                    if (cableTunnelCheck)
                        ShowHotCableTunnels(mousePopUpMode);
                    else
                        HideHotCableTunnels();
                    break;
                case TMouseActionMode.RulerMode:
                    rulerCheck = !rulerCheck;
                    MeasurementLayer.ReloadData();
                    break;
                case TMouseActionMode.MoveVertexMode:
                    moveVertexCheck = !moveVertexCheck;
                    break;
                case TMouseActionMode.None:
                    cableTunnelCheck = false;
                    rulerCheck = false;
                    moveVertexCheck = false;
                    break;
            }
        }

        private void ShowHotCableTunnels(OpticNetDesignPanel.TMousePopUpMode mousePopUpMode)
        {
            if (hotCableTunnels != null && mousePopUpMode == OpticNetDesignPanel.TMousePopUpMode.None) return;
            if (hotCableTunnels != null && mousePopUpMode == OpticNetDesignPanel.TMousePopUpMode.Normal)
            {
                hotCableTunnels.WindowState = FormWindowState.Normal;
                return;
            }

            if (hotCableTunnels != null && mousePopUpMode == OpticNetDesignPanel.TMousePopUpMode.Minimize)
            {
                hotCableTunnels.WindowState = FormWindowState.Minimized;
                return;
            }

            NetLayer.ClearLighted();

            hotCableTunnels = new FrmHotCableTunnels();
            hotCableTunnels.FormClosed += new FormClosedEventHandler(FrmHotCableTunnels_FormClosed);
            hotCableTunnels.Closed += new EventHandler(hotCableTunnels_Closed);
            hotCableTunnels.OnAcceptChanges += new EventHandler<CableTunnelList.AcceptChangesArgs>(FrmHotCableTunnels_OnAcceptChanges);

            hotCableTunnels.OnVertexChanges += new EventHandler<VertexList.AcceptChangesArgs>(hotCableTunnels_OnVertexChanges);
            hotCableTunnels.SizeChanged += new EventHandler(hotCableTunnels_SizeChanged);
            hotCableTunnels.OnCancelCableTunnel += new EventHandler<GlobalData.ListEventArgs>(hotCableTunnels_OnCancelCableTunnel);
            hotCableTunnels.OnCancelVertexes += new EventHandler<GlobalData.ListEventArgs>(hotCableTunnels_OnCancelVertexes);
            hotCableTunnels.Show(this.Parent);
            hotCableTunnels.WindowState = FormWindowState.Minimized;
        }
        public class BoolEvent : EventArgs
        {
            public bool BoolMessage { get; private set; }
            public BoolEvent(bool boolMessagr)
            {
                BoolMessage = boolMessagr;
            }
        }

        public event EventHandler<BoolEvent> CableTunnelsSizeChanged;
        void hotCableTunnels_SizeChanged(object sender, EventArgs e)
        {
            bool mess = hotCableTunnels.WindowState != FormWindowState.Minimized;
            if (CableTunnelsSizeChanged != null) CableTunnelsSizeChanged(this, new BoolEvent(mess));
        }

        void hotCableTunnels_OnCancelCableTunnel(object sender, GlobalData.ListEventArgs e)
        {
            if (e != null && e.IDList != null)
            {
                foreach (int item in e.IDList)
                    NetLayer.RemoveCableTunnel(item);
            }
        }

        void hotCableTunnels_OnCancelVertexes(object sender, GlobalData.ListEventArgs e)
        {
            if (e != null && e.IDList != null)
            {
                foreach (int item in e.IDList)
                    NetLayer.RemoveVertex(item);
            }
        }


        void hotCableTunnels_OnVertexChanges(object sender, VertexList.AcceptChangesArgs e)
        {
            NetLayer.MergeData(e.DataTable);
        }

        void hotCableTunnels_Closed(object sender, EventArgs e)
        {
            //     XtraMessageBox.Show("Не задано ни одного туннкля для прокладки", "Сообщение", MessageBoxButtons.OK);
        }

        private void HideHotCableTunnels()
        {
            if (hotCableTunnels != null)
                hotCableTunnels.Close();
        }

        private void FrmHotCableTunnels_FormClosed(object sender, FormClosedEventArgs e)
        {
            try
            {
                int cableID = hotCableTunnels.CableID;
                hotCableTunnels.Visible = false;
                hotCableTunnels = null;
                cableTunnelCheck = false;

                if (OnTurnOffEditMode != null)
                    OnTurnOffEditMode(this, EventArgs.Empty);

                if (cableID != 0)
                    if (XtraMessageBox.Show("Разварить кабель в колодцах(объектах)?", "Сообщение", MessageBoxButtons.YesNo,
                                            MessageBoxIcon.Exclamation) == DialogResult.Yes)
                    {
                        FrmVertexes frmVertexes = FrmVertexes.ShowForm(false);
                        frmVertexes.CableConnection(cableID);

                    }
            }
            catch
            {
            }
            finally
            {
                hotCableTunnels = null;
            }

        }

        private void FrmHotCableTunnels_OnAcceptChanges(object sender, CableTunnelList.AcceptChangesArgs e)
        {
            NetLayer.MergeData(e.DataTable);
        }

        private void OpticNetCtl_MouseDown(object sender, MouseEventArgs e)
        {
            if (MapLayer.Terminating) return;

            if (e.Button != MouseButtons.Left && e.Button != MouseButtons.Right) return;

            Coordinate coordinate = Coordinate.CoordinateFromScreen(NetLayer.GoogleScreenView, e.Location);

            HashItem[] VertexRows = null;
            HashItem[] CableTunnelRows = null;
            HashItem[] MeasurePoints = null;
            List<Task> tasks = new List<Task>();

            tasks.Add(Task.Factory.StartNew(delegate { VertexRows = NetLayer.FindNearestVertex(coordinate); }));
            tasks.Add(Task.Factory.StartNew(delegate { CableTunnelRows = NetLayer.FindNearestCableTunnel(coordinate); }));
            tasks.Add(Task.Factory.StartNew(delegate { MeasurePoints = MeasurementLayer.FindMeasurePoint(coordinate); }));
            Task.WaitAll(tasks.ToArray());

            if (e.Button == MouseButtons.Left)
            {
                bool newVertex = false;
                if (cableTunnelCheck && VertexRows.Length == 1 && CheckSecurityEditAction(false)
                           && hotCableTunnels != null)
                {
                    SimpleOpticNetDB.VertexesRow row = NetLayer.FindVertex(VertexRows[0].Value);
                    if (row != null)
                        newVertex = hotCableTunnels.AddVertex(row);
                }

                if (moveVertexCheck && VertexRows.Length == 1 && !newVertex && CheckSecurityEditAction(false))
                {
                    MapDragObject.StartExistingVertexDragDrop(this, e.Location, VertexRows[0].Value);
                }

                if (rulerCheck && MeasurePoints.Length > 0)
                {
                    MapDragObject.StartExistingMeasurePointDragDrop(this, e.Location, MeasurePoints[0].Value);
                }
                
                if (!CaptureMoveMap && VertexRows.Length == 0 && CableTunnelRows.Length == 0 
                    && ((rulerCheck && MeasurePoints.Length == 0)||!rulerCheck))
                {
                    CaptureMoveMap = true;
                    MousePreviousLocation = new Point(e.X, e.Y);
                    CoordinatePreviosLocation = CenterCoordinate;

                    if (_shiftKey && moveVertexCheck)
                    {
                        popupAddVertex.PerformClick();
                        //_shiftKey = false;
                        CaptureMoveMap = false;
                        MousePreviousLocation = new Point(e.X, e.Y);
                    }
                }
                
            }
            else if (e.Button == MouseButtons.Right)
            {
                MousePreviousLocation = new Point(e.X, e.Y);

                if (rulerCheck)
                {
                    MeasurementLayer.AddMeasure(coordinate);
                }
                else if (VertexRows.Length > 0)
                {
                    popupViewVertex.Enabled = VertexRows.Length == 1;
                    popupDeleteVertex.Enabled = VertexRows.Length == 1;
                    PreviousObjectID = VertexRows[0].Value;

                    popupVertexMenu.ShowPopup(MousePosition);
                }
                else if (CableTunnelRows.Length > 0)
                {
                    popupViewCableTunnel.Enabled = CableTunnelRows.Length == 1;
                    popupDeleteCableTunnel.Enabled = CableTunnelRows.Length == 1;
                    PreviousObjectID = CableTunnelRows[0].Value;

                    popupCableTunnelMenu.ShowPopup(MousePosition);
                }
                else
                {
                    PreviousObjectID = 0;
                    popupMapMenu.ShowPopup(MousePosition);
                }
            }
        }

        private void OpticNetCtl_MouseWheel(object sender, MouseEventArgs e)
        {
            if (e.Delta != 0)
            {
                int newZoom = Level;
                newZoom += (e.Delta > 0) ? 1 : -1;
                if (newZoom < 11)
                    newZoom = 11;
                else if (newZoom > 20)
                    newZoom = 20;
                Level = newZoom;
            }
        }

        private void OpticNetCtl_MouseUp(object sender, MouseEventArgs e)
        {
            CaptureMoveMap = false;
            MousePreviousLocation = new Point(e.X, e.Y);
        }

        private int? _element_ID = null;
        private void OpticNetCtl_MouseMove(object sender, MouseEventArgs e)
        {
            if (MapLayer.Terminating) return;
            Coordinate coordinate = Coordinate.CoordinateFromScreen(NetLayer.GoogleScreenView, e.Location);
            if (CaptureMoveMap)
            {
                int deltaX = MousePreviousLocation.X - e.X;
                int deltaY = MousePreviousLocation.Y - e.Y;

                Coordinate newCoords = CoordinatePreviosLocation + new GoogleCoordinate(deltaX, deltaY, Level);

                CenterCoordinate = newCoords;
            }
            else
            {
                HashItem[] VertexRows = null;
                HashItem[] CableTunnelRows = null;
                HashItem[] MeasurePoints = null;
                List<Task> tasks = new List<Task>();

                tasks.Add(Task.Factory.StartNew(delegate { VertexRows = NetLayer.FindNearestVertex(coordinate); }));
                tasks.Add(Task.Factory.StartNew(delegate { CableTunnelRows = NetLayer.FindNearestCableTunnel(coordinate); }));
                tasks.Add(Task.Factory.StartNew(delegate { MeasurePoints = MeasurementLayer.FindMeasurePoint(coordinate); }));
                Task.WaitAll(tasks.ToArray());

                if (VertexRows.Length > 0)
                {
                    vertexesTableAdapter.SelectCommandTimeout = ProgramMain.Properties.Settings.Default.LongQueryTimeout;
                    vertexesTableAdapter.ClearBeforeFill = true;
                    vertexesTableAdapter.Fill(simpleOpticNetDB.Vertexes, VertexRows[0].Value, null, null, null, null,
                                              null, null, null, null);
                    if (dsVertexes.Current != null)
                    {
                        SimpleOpticNetDB.VertexesRow row =
                            (SimpleOpticNetDB.VertexesRow)((DataRowView)dsVertexes.Current).Row;
                        if (!row.IsHintNull())
                            if (!_element_ID.HasValue || (_element_ID.HasValue && _element_ID != row.ID))
                            {
                                _element_ID = row.ID;
                                toolTip1.SetToolTip(this, row.Hint.Replace("***", "\n"));
                            }
                    }
                }
                if(rulerCheck && MeasurePoints.Length >0)
                { this.Cursor = Cursors.SizeAll; }
                else
                {
                    this.Cursor = Cursors.Default;
                }
                if (CableTunnelRows.Length > 0 && VertexRows.Length == 0)
                {
                    cableTunnelsTableAdapter.SelectCommandTimeout =
                        ProgramMain.Properties.Settings.Default.LongQueryTimeout;
                    cableTunnelsTableAdapter.ClearBeforeFill = true;
                    cableTunnelsTableAdapter.Fill(simpleOpticNetDB.CableTunnels, CableTunnelRows[0].Value, null, null,
                                                  null, null, null, null, null, null);
                    if (dsCableTunnels.Current != null)
                    {
                        {
                            SimpleOpticNetDB.CableTunnelsRow row =
                                (SimpleOpticNetDB.CableTunnelsRow)((DataRowView)dsCableTunnels.Current).Row;
                            if (!row.IsHINTNull())
                                if (!_element_ID.HasValue || (_element_ID.HasValue && _element_ID != row.ID))
                                {
                                    _element_ID = row.ID;
                                    toolTip1.SetToolTip(this, row.HINT.Replace("***", "\n"));
                                }
                        }
                    }
                }
                if (VertexRows.Length == 0 && CableTunnelRows.Length == 0)
                {
                    _element_ID = null;
                    toolTip1.Hide(this);
                }
            }
        }

        private void OpticNetCtl_DoubleClick(object sender, EventArgs e)
        {
            if (MapLayer.Terminating) return;

            Coordinate coordinate = Coordinate.CoordinateFromScreen(NetLayer.GoogleScreenView, MousePreviousLocation);

            HashItem[] VertexRows = null;
            HashItem[] CableTunnelRows = null;
            List<Task> tasks = new List<Task>();

            tasks.Add(Task.Factory.StartNew(delegate { VertexRows = NetLayer.FindNearestVertex(coordinate); }));
            tasks.Add(Task.Factory.StartNew(delegate { CableTunnelRows = NetLayer.FindNearestCableTunnel(coordinate); }));
            Task.WaitAll(tasks.ToArray());

            if (VertexRows.Length > 0)
            {
               barVertexMap.PerformClick();
                return;
            }
            if (CableTunnelRows.Length > 0)
            {
                EditCableTunnel(CableTunnelRows[0].Value);
                return;
            }

            CenterCoordinate = coordinate;
        }

        private void OpticNetCtl_DragEnter(object sender, DragEventArgs e)
        {
            logs.Add("DragEnter");
            if (MapLayer.Terminating)
            {
                e.Effect = DragDropEffects.None;
                return;
            }

            try
            {
                MapDragObject dragObject = MapDragObject.GetObject(this, e);
                if (dragObject != null && dragObject.DragObjectType == MapDragObject.DragObjectTypes.Vertex)
                {
                    e.Effect = dragObject.DragDropAction;
                    IsDragAndDropVertex = true;
                    PreviousObjectID = dragObject.ObjectID;
                    if (PreviousObjectID > 0)
                    {
                        vertexesTableAdapter.SelectCommandTimeout =
                            ProgramMain.Properties.Settings.Default.LongQueryTimeout;
                        vertexesTableAdapter.ClearBeforeFill = true;
                        vertexesTableAdapter.Fill(simpleOpticNetDB.Vertexes, PreviousObjectID, null, null, null, null,
                                                  null,
                                                  null, null, null);

                        cableTunnelsTableAdapter.SelectCommandTimeout =
                            ProgramMain.Properties.Settings.Default.LongQueryTimeout;
                        cableTunnelsTableAdapter.ClearBeforeFill = true;
                        cableTunnelsTableAdapter.Fill(simpleOpticNetDB.CableTunnels, null, PreviousObjectID, null, null,
                                                      null, null, null, null, null);

                        _dragVertex = (SimpleOpticNetDB.VertexesRow) ((DataRowView) dsVertexes.Current).Row;

                        _activeCableTunnels = new List<int>();
                        for (int i = 0; i < dsCableTunnels.Count; i++)
                        {
                            dsCableTunnels.Position = i;
                            SimpleOpticNetDB.CableTunnelsRow row =
                                (SimpleOpticNetDB.CableTunnelsRow) ((DataRowView) dsCableTunnels.Current).Row;
                            row.LocalAttribute = 1;
                            _activeCableTunnels.Add(row.ID);
                        }
                        dsCableTunnels.EndEdit();
                        _dragCableTunnelValue = e.X;
                    }
                }
                else if (dragObject != null && dragObject.DragObjectType == MapDragObject.DragObjectTypes.MeasurePoint)
                {
                    e.Effect = dragObject.DragDropAction;
                    _isDragAndDropMeause = true;
                }
                else
                {
                    e.Effect = DragDropEffects.None;
                }
            }
            catch (Exception)
            {
                e.Effect = DragDropEffects.None;
            }
        }

        private void OpticNetCtl_GiveFeedback(object sender, GiveFeedbackEventArgs e)
        {
            MapDragObject.ChangeCursor(e, MapDragObject.DragObjectTypes.Vertex);
        }

        private void OpticNetCtl_DragDrop(object sender, DragEventArgs e)
        {
            logs.Add("DragDROP");

            e.Effect = DragDropEffects.None;
            Cursor.Current = Cursors.Default;
            IsDragAndDropVertex = false;
            _isDragAndDropMeause = false;
             DragCtrl = false;
            DragAlt = false;
            MeasurementLayer.ClearOldCoordinate();

            MapDragObject dragObject = MapDragObject.GetObject(this, e);

            if (dragObject != null && dragObject.DragObjectType == MapDragObject.DragObjectTypes.Vertex)
            {
                if (dragObject.DragDropAction == DragDropEffects.Copy)
                {
                    Coordinate coordinate = Coordinate.CoordinateFromScreen(NetLayer.GoogleScreenView, dragObject.EndPoint);
                    if (hotCableTunnels == null)
                        AddVertex(dragObject.EndPoint);
                       // new VertexList() {AutoCloseDetail = _shiftKey}.AddVertex(coordinate);
                    else
                    {

                        if (Properties.Settings.Default.IsPutRule)
                        {
                            CoordinateRectangle measur = MeasurementLayer.GetNearestRectangle(coordinate);
                            if (measur != null)
                            {
                                coordinate = measur.GetNearestPoint(coordinate);
                            }
                        }
                        hotCableTunnels.AddVertex(coordinate);
                    }
                }
                else if (dragObject.DragDropAction == DragDropEffects.Move)
                {
                    if (dragObject.ObjectID > 0)
                    {
                        vertexesTableAdapter.SetUpdateTimeout = ProgramMain.Properties.Settings.Default.LongQueryTimeout;
                        vertexesTableAdapter.Update(simpleOpticNetDB.Vertexes);

                        NetLayer.MergeData(simpleOpticNetDB.Vertexes);

                        cableTunnelsTableAdapter.SelectCommandTimeout = ProgramMain.Properties.Settings.Default.LongQueryTimeout;
                        cableTunnelsTableAdapter.ClearBeforeFill = true;
                        cableTunnelsTableAdapter.Fill(simpleOpticNetDB.CableTunnels, null, dragObject.ObjectID, null,
                                                      null, null, null, null, null, null);

                        NetLayer.MergeData(simpleOpticNetDB.CableTunnels);
                    }
                }
            }

            if (dragObject != null && dragObject.DragObjectType == MapDragObject.DragObjectTypes.MeasurePoint)
            {
                if (dragObject.DragDropAction == DragDropEffects.Move && dragObject.ObjectID != 0)
                {
                  //  Coordinate coordinate = Coordinate.CoordinateFromScreen(NetLayer.GoogleScreenView, e.Location);
                }
            }
        }

        private void popupRefreshMap_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            RefreshControl();
        }

        private void AddVertex(Point pt)
        {
            if (!CheckSecurityEditAction()) return;

            VertexDetail dialog = new VertexDetail();
            dialog.AutoClose = _shiftKey;
            simpleOpticNetDB.Vertexes.Clear();
            dialog.dataSource = dsVertexes;
            dialog.dataSource.AddNew();
            SimpleOpticNetDB.VertexesRow row = (SimpleOpticNetDB.VertexesRow)((DataRowView)dialog.dataSource.Current).Row;

            Coordinate coordinate = Coordinate.CoordinateFromScreen(NetLayer.GoogleScreenView, pt);
            if (Properties.Settings.Default.IsPutRule)
            {
                CoordinateRectangle measur = MeasurementLayer.GetNearestRectangle(coordinate);
                if (measur != null)
                {
                    coordinate = measur.GetNearestPoint(coordinate);
                }
            }
            row.Longitude = Convert.ToDecimal(coordinate.Longitude);
            row.Latitude = Convert.ToDecimal(coordinate.Latitude);
            row.CaptionX = 15;
            row.CaptionY = 15;
            DialogResult dlgRes = dialog.ShowModal(BaseModalDetailCtl.ShowModeTypes.Add);
            if (dlgRes == DialogResult.OK)
            {
                try
                {
                    vertexesTableAdapter.SetUpdateTimeout = ProgramMain.Properties.Settings.Default.LongQueryTimeout;
                    vertexesTableAdapter.Update(simpleOpticNetDB.Vertexes);
                    NetLayer.MergeData(simpleOpticNetDB.Vertexes);
                }
                catch (Exception ex)
                {
                    ShowWriteError(ex);
                }
            }
        }

        private void EditVertex(int ObjectID, Coordinate coordinate)
        {
            VertexDetail dialog = new VertexDetail();

            vertexesTableAdapter.SelectCommandTimeout = ProgramMain.Properties.Settings.Default.LongQueryTimeout;
            vertexesTableAdapter.ClearBeforeFill = true;
            vertexesTableAdapter.Fill(simpleOpticNetDB.Vertexes, ObjectID, null, null, null, null, null, null, null, null);
            dialog.dataSource = dsVertexes;
            if (simpleOpticNetDB.Vertexes.Count > 0)
            {
                if (coordinate != null)
                {
                    SimpleOpticNetDB.VertexesRow row =
                        (SimpleOpticNetDB.VertexesRow)((DataRowView)dialog.dataSource.Current).Row;

                    row.Longitude = Convert.ToDecimal(coordinate.Longitude);
                    row.Latitude = Convert.ToDecimal(coordinate.Latitude);
                    row.UserID = ProgramMain.Framework.BaseSecurity.UserID;
                }

                bool isEditible = CheckSecurityEditAction(false);
                BaseModalDetailCtl.ShowModeTypes ShowMode = (isEditible) ? BaseModalDetailCtl.ShowModeTypes.Edit : BaseModalDetailCtl.ShowModeTypes.View;

                DialogResult dlgRes = dialog.ShowModal(ShowMode);
                if (dlgRes == DialogResult.OK)
                {
                    try
                    {
                        vertexesTableAdapter.SetUpdateTimeout = ProgramMain.Properties.Settings.Default.LongQueryTimeout;
                        vertexesTableAdapter.Update(simpleOpticNetDB.Vertexes);

                        NetLayer.MergeData(simpleOpticNetDB.Vertexes);

                        cableTunnelsTableAdapter.SelectCommandTimeout = ProgramMain.Properties.Settings.Default.LongQueryTimeout;
                        cableTunnelsTableAdapter.ClearBeforeFill = true;
                        cableTunnelsTableAdapter.Fill(simpleOpticNetDB.CableTunnels, null, ObjectID, null, null, null, null, null, null, null);

                        NetLayer.MergeData(simpleOpticNetDB.CableTunnels);
                    }
                    catch (Exception ex)
                    {
                        ShowWriteError(ex);
                    }
                }
            }
        }

        private void DeleteVertex(int ObjectID)
        {
            VertexDetail dialog = new VertexDetail();

            vertexesTableAdapter.SelectCommandTimeout = ProgramMain.Properties.Settings.Default.LongQueryTimeout;
            vertexesTableAdapter.ClearBeforeFill = true;
            vertexesTableAdapter.Fill(simpleOpticNetDB.Vertexes, ObjectID, null, null, null, null, null, null, null, null);
            dialog.dataSource = dsVertexes;
            if (simpleOpticNetDB.Vertexes.Count > 0)
            {
                if (!CheckSecurityDeleteAction())
                    return;
                SimpleOpticNetDB.VertexesRow rowvertes =
                       (SimpleOpticNetDB.VertexesRow)((DataRowView)dialog.dataSource.Current).Row;

                rowvertes.UserID = ProgramMain.Framework.BaseSecurity.UserID;
                dialog.dataSource.EndEdit();
                DialogResult dlgRes = dialog.ShowModal(BaseModalDetailCtl.ShowModeTypes.Delete);
                if (dlgRes == DialogResult.OK)
                {
                    try
                    {
                        cableTunnelsTableAdapter.SelectCommandTimeout = ProgramMain.Properties.Settings.Default.LongQueryTimeout;
                        cableTunnelsTableAdapter.ClearBeforeFill = true;
                        cableTunnelsTableAdapter.Fill(simpleOpticNetDB.CableTunnels, null, ObjectID, null, null, null, null, null, null, null);

                        foreach (SimpleOpticNetDB.CableTunnelsRow row in simpleOpticNetDB.CableTunnels.Rows)
                        {
                            NetLayer.RemoveCableTunnel(row.ID);
                        }

                        vertexesTableAdapter.SetUpdateTimeout = ProgramMain.Properties.Settings.Default.LongQueryTimeout;
                        vertexesTableAdapter.Update(simpleOpticNetDB.Vertexes);
                        NetLayer.RemoveVertex(ObjectID);
                        
                    }
                    catch (Exception ex)
                    {
                        ShowWriteError(ex);
                    }
                }
            }
        }

        public SimpleOpticNetDB.VertexesRow FindVertex(int vertexID)
        {
            int v = this.dsVertexes.Find("ID", vertexID);
            if (v > -1)
            {
                dsVertexes.Position = v;
                SimpleOpticNetDB.VertexesRow row = (SimpleOpticNetDB.VertexesRow)((DataRowView)dsVertexes.Current).Row;
                return row;
            }
            else
            {
                return null;
            }
        }

        private void DragDropMoveVertex(int ObjectID, Coordinate coordinate)
        {
            SimpleOpticNetDB.VertexesRow vertex = FindVertex(ObjectID);
            if (vertex == null) return;
            Coordinate oldCoordinate = new Coordinate(vertex.Longitude, vertex.Latitude);
            vertex.Longitude = (decimal)coordinate.Longitude;
            vertex.Latitude = (decimal)coordinate.Latitude;
            vertex.UserID = ProgramMain.Framework.BaseSecurity.UserID;
            vertex.EndEdit();

            dsCableTunnels.MoveFirst();
            int count = this.dsCableTunnels.Count;
            for (int index = 0; index < count; index++)
            {
                dsCableTunnels.Position = index;
                SimpleOpticNetDB.CableTunnelsRow row = (SimpleOpticNetDB.CableTunnelsRow)((DataRowView)dsCableTunnels.Current).Row;
                if (row.Latitude1 == (decimal)oldCoordinate.Latitude && row.Longitude1 == (decimal)oldCoordinate.Longitude)
                {
                    row.Latitude1 = (decimal)coordinate.Latitude;
                    row.Longitude1 = (decimal)coordinate.Longitude;
                }

                if (row.Latitude2 == (decimal)oldCoordinate.Latitude && row.Longitude2 == (decimal)oldCoordinate.Longitude)
                {
                    row.Latitude2 = (decimal)coordinate.Latitude;
                    row.Longitude2 = (decimal)coordinate.Longitude;
                }
                row.UserID = ProgramMain.Framework.BaseSecurity.UserID;
            }
            
            dsCableTunnels.EndEdit();
            NetLayer.MergeData(simpleOpticNetDB.Vertexes);
            NetLayer.MergeData(simpleOpticNetDB.CableTunnels);
        }
        private void MoveVertex(int ObjectID, Coordinate coordinate)
        {
            if (!CheckSecurityEditAction()) return;
            if (ObjectID == 0) return;
            if (ObjectID > 0)
                DragDropMoveVertex(ObjectID, coordinate);
            if (hotCableTunnels != null)
            {
                hotCableTunnels.EditCoordinateNewVertex(ObjectID, coordinate);
            }
        }

        private void EditCableTunnel(int ObjectID)
        {
            CableTunnelDetail dialog = new CableTunnelDetail();

            cableTunnelsTableAdapter.SelectCommandTimeout = ProgramMain.Properties.Settings.Default.LongQueryTimeout;
            cableTunnelsTableAdapter.ClearBeforeFill = true;
            cableTunnelsTableAdapter.Fill(simpleOpticNetDB.CableTunnels, ObjectID, null, null, null, null, null, null, null, null);
            if (simpleOpticNetDB.CableTunnels.Count > 0)
            {
                dialog.dataSource = dsCableTunnels;

                bool isEditible = CheckSecurityEditAction(false);
                BaseModalDetailCtl.ShowModeTypes ShowMode = (isEditible) ? BaseModalDetailCtl.ShowModeTypes.Edit : BaseModalDetailCtl.ShowModeTypes.View;

                DialogResult dlgRes = dialog.ShowModal(ShowMode);
                if (dlgRes == DialogResult.OK)
                {
                    try
                    {
                        cableTunnelsTableAdapter.SetUpdateTimeout = ProgramMain.Properties.Settings.Default.LongQueryTimeout;
                        cableTunnelsTableAdapter.Update(simpleOpticNetDB.CableTunnels);

                        NetLayer.MergeData(simpleOpticNetDB.CableTunnels);
                    }
                    catch (Exception ex)
                    {
                        ShowWriteError(ex);
                    }
                }
            }
        }

        private void DeleteCableTunnel(int ObjectID)
        {
            CableTunnelDetail dialog = new CableTunnelDetail();

            cableTunnelsTableAdapter.SelectCommandTimeout = ProgramMain.Properties.Settings.Default.LongQueryTimeout;
            cableTunnelsTableAdapter.ClearBeforeFill = true;
            cableTunnelsTableAdapter.Fill(simpleOpticNetDB.CableTunnels, ObjectID, null, null, null, null, null, null, null, null);
            if (simpleOpticNetDB.CableTunnels.Count > 0)
            {
                dialog.dataSource = dsCableTunnels;

                if (!CheckSecurityDeleteAction())
                    return;

                DialogResult dlgRes = dialog.ShowModal(BaseModalDetailCtl.ShowModeTypes.Delete);
                if (dlgRes == DialogResult.OK)
                {
                    try
                    {
                        cableTunnelsTableAdapter.SetUpdateTimeout = ProgramMain.Properties.Settings.Default.LongQueryTimeout;
                        cableTunnelsTableAdapter.Update(simpleOpticNetDB.CableTunnels);

                        NetLayer.RemoveCableTunnel(ObjectID);
                    }
                    catch (Exception ex)
                    {
                        ShowWriteError(ex);
                    }
                }
            }
        }

        private void popupAddVertex_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (!CheckSecurityEditAction()) return;
            Coordinate coordinate = Coordinate.CoordinateFromScreen(NetLayer.GoogleScreenView, MousePreviousLocation);
            if (hotCableTunnels == null)
            {
                AddVertex(MousePreviousLocation);
            }
            else
            {
                 CoordinateRectangle measur = MeasurementLayer.GetNearestRectangle(coordinate);
                if (measur != null)
                {
                    coordinate = measur.GetNearestPoint(coordinate);
                }
                hotCableTunnels.AddVertex(coordinate);

            }
        }

        private void popupShowVertexes_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (!Framework.BaseSecurity.CheckSecurityViewAction()) return;
            if (PreviousObjectID == 0)
                FrmVertexes.ShowForm(true);
            else
            {
                FrmVertexes frm = FrmVertexes.ShowForm(false);
                Coordinate coordinate = Coordinate.CoordinateFromScreen(NetLayer.GoogleScreenView, MousePreviousLocation);
                frm.SetNearPoint(coordinate, (int)NetLayer.CoordinateTolerance);
            }
        }

        private void popupShowCableTunnels_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (!Framework.BaseSecurity.CheckSecurityViewAction()) return;
            if (PreviousObjectID == 0)
                FrmCableTunnels.ShowForm(true);
            else
            {
                FrmCableTunnels frm = FrmCableTunnels.ShowForm(false);
                Coordinate coordinate = Coordinate.CoordinateFromScreen(NetLayer.GoogleScreenView, MousePreviousLocation);
                frm.SetNearPoint(coordinate, (int)NetLayer.CoordinateTolerance);
            }
        }

        private void popupViewVertex_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (!Framework.BaseSecurity.CheckSecurityViewAction()) return;
            if( PreviousObjectID >0)
            EditVertex(PreviousObjectID, null);
            else if(PreviousObjectID <0 && hotCableTunnels!= null)
                hotCableTunnels.EditNewVertex(PreviousObjectID);
        }

        private void popupViewCableTunnel_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (!CheckSecurityEditAction()) return;
            if (PreviousObjectID > 0)
            EditCableTunnel(PreviousObjectID);
            else if(PreviousObjectID <0 && hotCableTunnels != null)
                hotCableTunnels.EditNewCableTunnel(PreviousObjectID);
        }

        private void popupDeleteVertex_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (!CheckSecurityEditAction()) return; 
            if (PreviousObjectID > 0)
            {
                DeleteVertex(PreviousObjectID);
            }

            if(PreviousObjectID <0 && hotCableTunnels != null)
                hotCableTunnels.DeleteVertex(PreviousObjectID);
        }

        private void popupDeleteCableTunnel_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (!CheckSecurityEditAction()) return;
            if (PreviousObjectID > 0)
            {
                DeleteCableTunnel(PreviousObjectID);
            }
            if (PreviousObjectID < 0 && hotCableTunnels != null)
                hotCableTunnels.DeleteCableTunnel(PreviousObjectID);
        }

        private void barVertexMap_ItemClick(object sender, ItemClickEventArgs e)
        {
            if (!Framework.BaseSecurity.CheckSecurityViewAction()) return;
            FrmVertexMap.ShowForm(false, PreviousObjectID);
        }


        private void OpticNetCtl_Leave(object sender, EventArgs e)
        {
            // CloseHint();
        }

        public void AddFreeLine(NetLayer.FreeLine freeLine)
        {
            NetLayer.AddFreeLine(freeLine);
        }

        public void AddMapPoint(Coordinate coordinate)
        {
            NetLayer.AddMapPoint(coordinate);
        }

        public void AddVertesLighted(int vertexID)
        {
            NetLayer.AddVertesLighted(vertexID);
        }

        public void RemoveVertesLighted(int vertexID)
        {
            NetLayer.RemoveVertesLighted(vertexID);
        }

        public void AddCableTunnelLighted(int cableTunnelID)
        {
            NetLayer.AddCableTunnelLighted(cableTunnelID);
        }

        public void RemoveCableTunnelLighted(int cableTunnelID)
        {
            NetLayer.RemoveVertesLighted(cableTunnelID);
        }
        public void ClearLighted()
        {
            NetLayer.ClearLighted();
        }

        private void ShowAddress_ItemClick(object sender, ItemClickEventArgs e)
        {
            Coordinate coordinate = Coordinate.CoordinateFromScreen(NetLayer.GoogleScreenView, MousePreviousLocation);
            GoogleSearch.GoogleSearch search = new GoogleSearch.GoogleSearch(coordinate);
            List<GoogleSearch.SearchResult> results = search.Search();
            if (results.Count > 0)
            {
                XtraMessageBox.Show(results[0].Address, "Информация", MessageBoxButtons.OK);
            }
        }

        private void ShowAddressAddVertex_ItemClick(object sender, ItemClickEventArgs e)
        {
            Coordinate coordinate = Coordinate.CoordinateFromScreen(NetLayer.GoogleScreenView, MousePreviousLocation);
            GoogleSearch.GoogleSearch search = new GoogleSearch.GoogleSearch(coordinate);
            List<GoogleSearch.SearchResult> results = search.Search();
            if (results.Count > 0)
            {
                if (CheckSecurityEditAction(false))
                {
                    if (XtraMessageBox.Show(string.Format("{0}\n\rДобавить объект(колодец) по указаному адресу?", results[0].Address), "Информация", MessageBoxButtons.YesNo) == DialogResult.Yes)
                    {
                        popupAddVertex_ItemClick(sender, e);
                    }
                }
                else
                {
                    XtraMessageBox.Show(results[0].Address, "Информация", MessageBoxButtons.OK);
                }
            }
        }

        private void DistanceEdit_ItemClick(object sender, ItemClickEventArgs e)
        {
            if (!CheckSecurityEditAction()) return;
            if (PreviousObjectID > 0)
            {
                FrmCableTunnelDistanceEdit cableTunnelDistanceEdit = new FrmCableTunnelDistanceEdit();

                cableTunnelDistanceEdit.DetailID = PreviousObjectID;
                if (cableTunnelDistanceEdit.ShowDialog() == DialogResult.OK)
                    this.RefreshControl();
            }
        }

        private void PutRule_ItemClick(object sender, ItemClickEventArgs e)
        {
            if (PreviousObjectID > 0)
                try
                {
                    vertexesTableAdapter.SelectCommandTimeout = ProgramMain.Properties.Settings.Default.LongQueryTimeout;
                    vertexesTableAdapter.ClearBeforeFill = true;
                    vertexesTableAdapter.Fill(simpleOpticNetDB.Vertexes, PreviousObjectID, null, null, null, null, null, null, null, null);

                    if (dsVertexes.Current != null)
                    {
                        SimpleOpticNetDB.VertexesRow row = (SimpleOpticNetDB.VertexesRow)((DataRowView)dsVertexes.Current).Row;
                        Coordinate coordinate = new Coordinate(row.Longitude, row.Latitude);
                        CoordinateRectangle measur = MeasurementLayer.GetNearestRectangle(coordinate);
                        if (measur != null)
                        {
                            coordinate = measur.GetNearestPoint(coordinate);
                            row.Longitude = Convert.ToDecimal(coordinate.Longitude);
                            row.Latitude = Convert.ToDecimal(coordinate.Latitude);
                            row.EndEdit();
                            vertexesTableAdapter.SetUpdateTimeout = ProgramMain.Properties.Settings.Default.LongQueryTimeout;
                            vertexesTableAdapter.Update(simpleOpticNetDB.Vertexes);

                            NetLayer.MergeData(simpleOpticNetDB.Vertexes);

                            cableTunnelsTableAdapter.SelectCommandTimeout = ProgramMain.Properties.Settings.Default.LongQueryTimeout;
                            cableTunnelsTableAdapter.ClearBeforeFill = true;
                            cableTunnelsTableAdapter.Fill(simpleOpticNetDB.CableTunnels, null, PreviousObjectID, null, null, null, null, null, null, null);

                            NetLayer.MergeData(simpleOpticNetDB.CableTunnels);
                        }

                    }


                }
                catch (Exception)
                { }

        }

        public void ClearMeasureRule()
        {
            MeasurementLayer.ClearMeasureData();
        }
        private void ClearMeasure_ItemClick(object sender, ItemClickEventArgs e)
        {
            ClearMeasureRule();
        }
        
        private Coordinate _DragCtrlMove(Coordinate fix, SimpleOpticNetDB.VertexesRow edit, Coordinate mouseCoordinate)
         {
             Coordinate mp = new Coordinate(edit.Longitude, edit.Latitude);
             double X = 0;
             double Y = 0;

             double[,] matrix = new double[2,3];

             matrix[0, 0] = (fix.Latitude - mp.Latitude);//x
             matrix[0, 1] = -(fix.Longitude - mp.Longitude);//y
             matrix[0, 2] = (fix.Latitude - mp.Latitude) * -fix.Longitude - (fix.Longitude - mp.Longitude) * -fix.Latitude;

             matrix[1, 2] = matrix[0, 1] * -mouseCoordinate.Longitude - matrix[0, 0] * -mouseCoordinate.Latitude;
             matrix[1, 0] = matrix[0, 1];
             matrix[1, 1] = -matrix[0, 0];
             double k0;
             if (matrix[0, 0] == 0)
             {
                 k0 = matrix[0, 0]; matrix[0, 0] = matrix[1, 0]; matrix[1, 0] = k0;
                 k0 = matrix[0, 1]; matrix[0, 1] = matrix[1, 1]; matrix[1, 1] = k0;
                 k0 = matrix[0, 2]; matrix[0, 2] = matrix[1, 2]; matrix[1, 2] = k0;
             }
             else
             {
                 k0 = matrix[1, 0]/matrix[0, 0]*-1;
                 matrix[1, 0] += (matrix[0, 0]*k0);
                 matrix[1, 1] += (matrix[0, 1]*k0);
                 matrix[1, 2] += (matrix[0, 2]*k0);
             }


             if (Math.Abs(matrix[1, 0]) > 0.001) return null;
             Y = -matrix[1, 2] / matrix[1, 1];
             X =-(matrix[0, 2] + Y * matrix[0, 1]) / matrix[0, 0];
             if (double.IsNaN(Y)) Y = mp.Latitude;
             if (double.IsNaN(X)) X = mp.Longitude;
             return new Coordinate(Math.Round(X, 5), Math.Round(Y, 5));
         }

        private Coordinate _DragAltMove(Coordinate fix, SimpleOpticNetDB.VertexesRow edit, Coordinate mouseCoordinate)
        {
            Coordinate res = new Coordinate(edit.Longitude, edit.Latitude);
            double len = fix.Distance(mouseCoordinate);
            double l = len/_dragLength;

            res.Longitude = fix.Longitude + (mouseCoordinate.Longitude - fix.Longitude) / l;
            res.Latitude = fix.Latitude + (mouseCoordinate.Latitude - fix.Latitude) / l;

            return res;
        }

        private void OpticNetCtl_DragOver(object sender, DragEventArgs e)
        {
            logs.Add("DragOver");
            DragCtrl = e.KeyState == 9;
            DragAlt = e.KeyState == 33;
            if (!CheckSecurityEditAction()) return;

            Coordinate coordinate = null;
            Point point = PointToClient(new Point(e.X, e.Y));
            if (DragCtrl && _dragCableTunnelValue > 0)
            {
                coordinate = _DragCtrlMove(_dragFixCoordinate, _dragVertex, Coordinate.CoordinateFromScreen(NetLayer.GoogleScreenView, point));
            
            }
            else if (DragAlt && _dragCableTunnelValue > 0)
            {
                coordinate = _DragAltMove(_dragFixCoordinate, _dragVertex, Coordinate.CoordinateFromScreen(NetLayer.GoogleScreenView, point));
            }
            else  coordinate = Coordinate.CoordinateFromScreen(NetLayer.GoogleScreenView, point);
         //   _dragCableTunnelValue = (DragCtrl || DragAlt) ? e.X : 0;
            if (IsDragAndDropVertex)
            {
                MoveVertex(PreviousObjectID, coordinate);
            }
            if (_isDragAndDropMeause && MeasurementLayer != null)
            {
                MapDragObject dragObject = MapDragObject.GetObject(this, e);
                if (dragObject == null) return;
                SimpleOpticNetDB.MeasuresRow row = MeasurementLayer.FindFirst(dragObject.ObjectID);
                if (row != null)
                {
                    Coordinate c1 = new Coordinate(row.Longitude1, row.Latitude1);
                    Coordinate c2 = new Coordinate(row.Longitude2, row.Latitude2);
                    if (coordinate.Distance(c1) < coordinate.Distance(c2))
                        coordinate = c1;
                    else
                        coordinate = c2;
                }
                MeasurementLayer.EditMeasure(coordinate);
            }
        }

        private void CaptionPosition_ItemClick(object sender, ItemClickEventArgs e)
        {
            if (!Framework.BaseSecurity.CheckSecurityTechAction()) return;
            if (!CheckSecurityEditAction()) return;
            BaseModalDetailCtl.ShowModeTypes ShowMode = BaseModalDetailCtl.ShowModeTypes.Edit;
            VertexCaptionDetail dialog = new VertexCaptionDetail();
            
            dialog.dataSource = dsVertexes;

            DialogResult dlgRes = dialog.ShowModal(ShowMode);
            if (dlgRes == DialogResult.OK)
            {
                try
                {
                    vertexesTableAdapter.SetUpdateTimeout = ProgramMain.Properties.Settings.Default.LongQueryTimeout;
                    vertexesTableAdapter.Update(simpleOpticNetDB.Vertexes);

                    NetLayer.MergeData(simpleOpticNetDB.Vertexes);
                }
                catch (Exception)
                {
                    
                }
            }
        }

        private void VertexAddDocument_ItemClick(object sender, ItemClickEventArgs e)
        {
            if (!CheckSecurityEditAction()) return;
            new DocumentList() {VertexID = PreviousObjectID}.AddDocument();
        }

        private void VertexDocument_ItemClick(object sender, ItemClickEventArgs e)
        {
            if (!Framework.BaseSecurity.CheckSecurityViewAction()) return;
            new FrmDocumentList() {VertexID = PreviousObjectID}.ShowDialog();
        }

        private void CableTunnelAddDocument_ItemClick(object sender, ItemClickEventArgs e)
        {
          //  if (!CheckSecurityEditAction()) return;
            if (!Framework.BaseSecurity.CheckSecurityTechAction()) return;
            new DocumentList() { CableTunnelID = PreviousObjectID }.AddDocument();
        }

        private void CableTunnelDocuments_ItemClick(object sender, ItemClickEventArgs e)
        {
            if (!Framework.BaseSecurity.CheckSecurityViewAction()) return;
            new FrmDocumentList() { CableTunnelID = PreviousObjectID }.ShowDialog();
        }

        private void OpticNetCtl_KeyUp(object sender, KeyEventArgs e)
        {
            _shiftKey = false;
            if(hotCableTunnels !=null) hotCableTunnels.AutoCloseVertexDetail = _shiftKey;
        }

        private int? _dragCableTunnel { get; set; }
        private int _dragCableTunnelValue { get; set; }

        private bool _dragCtrl = false;
        protected bool DragCtrl
        {  get { return _dragCtrl; }
            set
            {
                if (_dragCtrl != value)
                {
                    _dragCtrl = value;
                    if (value) DragSelectCableTunnel();
                    else if (NetLayer != null) NetLayer.ClearLighted();
                }
            }
        }

        private double _dragLength;

        private bool _dragAlt = false;
        protected bool DragAlt
        {
            get { return _dragAlt; }
            set
            {
                if (_dragAlt != value)
                {
                    _dragAlt = value;
                    if (value) DragSelectCableTunnel();
                    else if (NetLayer != null) NetLayer.ClearLighted();
                }
            }
        }

        private SimpleOpticNetDB.VertexesRow _dragVertex;

        private List<int> _activeCableTunnels = null;
        private Coordinate _dragFixCoordinate = null;

        private void DragSelectCableTunnel()
        {
            if (_activeCableTunnels == null) return;
            if(_dragCableTunnel.HasValue && NetLayer != null)
            {
                NetLayer.RemoveCableTunnelLighted(_dragCableTunnel.Value);
                int index = _activeCableTunnels.IndexOf(_dragCableTunnel.Value);
                if (index == _activeCableTunnels.Count - 1) index = 0;
                else index++;
                _dragCableTunnel = _activeCableTunnels[index];
            }
            else
            _dragCableTunnel = _activeCableTunnels[0];

            if (NetLayer != null)
            {
                NetLayer.AddCableTunnelLighted(_dragCableTunnel.Value);
                if (_dragVertex != null)
                {
                    SimpleOpticNetDB.CableTunnelsRow ctr;
                    int v = this.dsCableTunnels.Find("ID", _dragCableTunnel.Value);
                    if (v > -1)
                    {
                        dsCableTunnels.Position = v;
                        ctr = (SimpleOpticNetDB.CableTunnelsRow) ((DataRowView) dsCableTunnels.Current).Row;
                    }
                    else
                        ctr = null;

                    if(ctr !=null)
                    {
                        if (ctr.Longitude1 == _dragVertex.Longitude && ctr.Latitude1 == _dragVertex.Latitude) _dragFixCoordinate = new Coordinate(ctr.Longitude2, ctr.Latitude2);
                        if (ctr.Longitude2 == _dragVertex.Longitude && ctr.Latitude2 == _dragVertex.Latitude) _dragFixCoordinate = new Coordinate(ctr.Longitude1, ctr.Latitude1);
                        _dragLength = new Coordinate(_dragVertex.Longitude, _dragVertex.Latitude).Distance(_dragFixCoordinate);
                    }
                }
            }
        }

        private void OpticNetCtl_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.ShiftKey)
            {
                _shiftKey = e.KeyCode == Keys.ShiftKey;
                if (hotCableTunnels != null) hotCableTunnels.AutoCloseVertexDetail = _shiftKey;
                return;
            }
        }

        private List<string> logs = new List<string>();
    }
}